home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / DOC / TC_PARM.TXT < prev    next >
Encoding:
Text File  |  1997-02-07  |  9.7 KB  |  273 lines

  1. Von: Michael Seyfried @ STA (So, 23.09.90 19:49)
  2.  
  3. >Reg-Übergabe wie TC: (Auszüge aus TC Bunutzerhandbuch Seite 155ff)
  4.  
  5. [Zitat on]
  6. [..]
  7. Normalerweise werden die Parameter nach einer gemischten Register/Stack-
  8. Konvention übergeben. Das bedeudet, daß solange wie möglich die schnelle
  9. Registerübergabe versucht wird und erst dann der Stack verwendet wird. Daten-
  10. typen wie char, int oder long werden in den Datenregistern D0-D2 übergeben.
  11. Adreßparameter (Zeiger) kommen in die Register A0-A1. Fließkommavariablen,
  12. wie float, double und long double werden immer über den Stack übergeben.
  13. Im Falle von Funktionen mit variabler Parameterzahl erfolgt die Übergabe
  14. in jedem Fall über den Stack. Dasselbe trifft für Funktionen zu, die
  15. explizit mit den Schlüsselworten pascal und cdecl deklariert wurden.
  16.  
  17. Das Übergabeformat von C
  18.  
  19. [..]
  20. Die Register D0-D2 und A0-A1 dienen als Parameterregister. Diese Register
  21. müssen naturgemäß nicht gesichert werden. Sie werden zum Teil auch für die
  22. Rückgabe von Ergebnissen verwendet. Skalare Parameter mit einer 8-, 16- oder
  23. 32-Bit Darstellung (z.B: char, int, long, *(Zeiger)) werden in Registern über-
  24. geben, soweit ausreichend Parameterregister zur Verfügung stehen. Dabei erfolgt
  25. die Zuteilung von Parametern auf Register getrennt nach Adreß- und Daten-
  26. parametern entsprechend folgender Konvention (1):
  27.  
  28. 1. Der erste Adreßparameter wird in A0 übergeben, der zweite in A1, alle
  29.    anderen auf dem Stack.
  30.  
  31. 2. Anschließend wird der erste skalare Parameter in D0 übergeben, der zweite
  32.    in D1, der dritte in D2, alle anderen auf dem Stack.
  33.  
  34. [..]
  35.  
  36. Diese Konvention gilt für alle Standardfunktionen. Funktionen mit variabler
  37. Parameterzahl arbeiten jedoch nur mit Stackübergabe. Das bedeutet, daß für
  38. die Übergabe keine Register verwendet werden (2). [..]
  39. Bei der reinen Stackübergabe, die sich übrigens mit der expliziten Verwen-
  40. dung des Schlüsselworts cdecl erzwingen läßt, werden die Parameter in umge-
  41. kehrter Reihenfolge auf den Stack gelegt. Wenn das Schlüsselwort pascal ver-
  42. wendet wird, werden die Parameter in der Reihenfolge der Argumente auf den
  43. Stack gelegt. [..]
  44.  
  45. Wer ist wann für den Stack verantwortlich?
  46.  
  47. Bei allen normal und mit cdecl deklarierten Funktionen muß die aufrufende
  48. Funktion nach dem Aufruf die Parameter selbst vom Stack holen (z.B: mit
  49. ADDQ.W #8, A7). Dies erübrigt sich natürlich, wenn alle Parameter in Registern
  50. übergeben wurden.
  51. Eine als pascal deklarierte Funktion räumt alle ihre Parameter vor der Rück-
  52. kehr selbst vom Stack ab. Nur die Funktionsresultate bleiben auf dem Stack.
  53.  
  54. [..]
  55. Funktionsresultate
  56. [..]
  57.  
  58. Für die Rückgabe von Funktionswerten gelten allgemein folgende Regeln:
  59.  
  60. - Die Datentypen char, int, enum, und long werden im Register D0 zu-
  61.   rückgeliefert. Zeigerresultate werden über A0 zurückgegeben.
  62. - Strukturen und Verbände (struct und union) werden per Adresse in A0
  63.   zurückgegeben. Die Adresse der temponären Speicherstelle wird als letzter
  64.   Parameter in den Adreßregistern beziehungsweise am Stack abgelegt (3).
  65.  
  66. Erlaubete und unerlaubte Verwendung von Registern
  67.  
  68. Die Register D3-D7 und A2-A6 müssen von allen Routinen gerettet werden, falls
  69. sie verwendet werden. Diese Register werden vom Compiler intern verwendet und
  70. stehen aus diesem Grunde nicht zur freien Verfügung.
  71. [Zitat off]
  72.  
  73. Anmerkungen:
  74.  
  75. ad 1:   In dieser Regel wird leider wenig über die Reihenfolge der Parameter,
  76.         die nicht in Register passen, auf dem Stack gesagt. Das wird folgen-
  77.         dermaßen gehandhabt:
  78.         a) Alle Parameter, die in Register passen werden gemäß 1. und 2. in
  79.            Registern übergeben.
  80.         b) Alle übrigen Parameter werden in der Reihenfolge von rechts nach
  81.            links auf dem Stack übergeben. Siehe dazu Beispiel weiter unten.
  82. ad 2:   Daß gar keine Register verwendet werden stimmt nicht. Die festen
  83.         Parameter (z.B der Formatstring bei 'printf') werden nach der
  84.         Standardkonvention (d.h. in Registern/Stack) übergeben. Alle variablen
  85.         Parameter (z.B bei 'printf' alle Parameter nach dem Formatstring)
  86.         werden in Reihenfolge von rechts nach links auf dem Stack übergeben.
  87.         Siehe dazu ebenfalls Beispiel weiter unten.
  88.         Da es aber in Modula-2 keine Prozeduren mit variabler Parameteranzahl
  89.         gibt, müssen solche Prozeduren gesondert behandelt werden. Ich könnte
  90.         vorerst ohne direkte Unterstützung dieser speziellen Parameter-
  91.         übergabeart leben.
  92. ad 3:   Diese Regel gilt offensichtlich für alle Datenstrukturen >32-Bit,
  93.         also insbesondere auch für float, double , und long double.
  94.  
  95.  
  96. Beispielprogramm:
  97.  
  98. int printf(const char *format, ... ); /* Prototyp */
  99.  
  100. double p1(int i1,
  101.           int *p1,
  102.           int i2,
  103.           int *p2,
  104.           double d1,
  105.           double *p3,
  106.           int i3,
  107.           int *p4,
  108.           int i4,
  109.           int *p5)
  110. {
  111.   *p1 = i1;
  112.   *p2 = i2;
  113.   *p3 = d1;
  114.   *p4 = i3;
  115.   *p5 = i4;
  116.   return i1 + i2 + i3 + i4 + d1;
  117. }
  118.  
  119. int i1, i2, i3, i4;
  120. double d1, d;
  121.  
  122. void main( void)
  123. {
  124.    d = p1( 1, &i1, 2, &i2, 0.123456789, &d1, 3, &i3, 4, &i4);
  125.    printf( "d: %10lf  i1: %10d\n", d, i1);
  126. }
  127.  
  128. Was der Compiler daraus macht (siehe Kommentar ab 'main'):
  129.  
  130. DISPOBJ  Object file browser                Borland Intl. Scotts Valley
  131. Copyright (C) 1990                          All Rights reserved
  132. Version 1.00
  133.  
  134. * Object File "tcparam1"
  135.  
  136.  
  137.           .TEXT
  138.  
  139.           .MODULE GLOBAL
  140.  
  141. p1:
  142. T000000:   MOVE.W    D6,-(A7)
  143. T000002:   LEA.L     -$000A(A7),A7
  144. T000006:   MOVE.W    $0026(A7),D6
  145. T00000A:   MOVE.W    D0,(A0)
  146. T00000C:   MOVE.W    D1,(A1)
  147. T00000E:   MOVEA.L   $001E(A7),A0
  148. T000012:   LEA.L     $0014(A7),A1
  149. T000016:   MOVE.L    (A1)+,(A0)+
  150. T000018:   MOVE.L    (A1)+,(A0)+
  151. T00001A:   MOVE.W    (A1)+,(A0)+
  152. T00001C:   MOVEA.L   $0022(A7),A0
  153. T000020:   MOVE.W    D2,(A0)
  154. T000022:   MOVEA.L   $0028(A7),A1
  155. T000026:   MOVE.W    D6,(A1)
  156. T000028:   ADD.W     D1,D0
  157. T00002A:   ADD.W     D2,D0
  158. T00002C:   ADD.W     D6,D0
  159. T00002E:   LEA.L     (A7),A0
  160. T000030:   JSR       _wxcnv(PC)
  161. T000034:   LEA.L     (A7),A0
  162. T000036:   LEA.L     $0014(A7),A1
  163. T00003A:   JSR       _xxadd(PC)
  164. T00003E:   MOVEA.L   $0010(A7),A0
  165. T000042:   LEA.L     (A7),A1
  166. T000044:   MOVE.L    (A1)+,(A0)+
  167. T000046:   MOVE.L    (A1)+,(A0)+
  168. T000048:   MOVE.W    (A1)+,(A0)+
  169. T00004A:   LEA.L     $000A(A7),A7
  170. T00004E:   MOVE.W    (A7)+,D6
  171. T000050:   RTS
  172.  
  173.           .MODULE GLOBAL
  174.  
  175. main:
  176. T000000:   MOVE.L    A2,-(A7)       ; A2 wird gerettet
  177. T000002:   LEA.L     -$000A(A7),A7  ; 10 Bytes auf Stack für Returnwert
  178. T000006:   LEA.L     i1,A2          ; Basisadresse der Var's nach A2
  179. T00000C:   PEA.L     i4             ; Adresse von i4 auf Stack
  180. T000012:   MOVEQ.L   #$04,D0
  181. T000014:   MOVE.W    D0,-(A7)       ; Wert 4 auf Stack
  182. T000016:   PEA.L     i3             ; Adresse von i3 auf Stack
  183. T00001C:   PEA.L     d1             ; Adresse von d1 auf Stack
  184. T000022:   LEA.L     +$0000001E,A0  ; 0.123456789 auf Stack
  185. T000028:   MOVE.L    -(A0),-(A7)
  186. T00002A:   MOVE.L    -(A0),-(A7)
  187. T00002C:   MOVE.W    -(A0),-(A7)
  188. T00002E:   MOVEQ.L   #$03,D2        ; Wert 3 in Parameterregister D2
  189. T000030:   LEA.L     $0002(A2),A1   ; Adresse von i2 in Parameterregister A1
  190. T000034:   MOVEQ.L   #$02,D1        ; Wert 2 in Parameterregister D1
  191. T000036:   MOVEA.L   A2,A0          ; Adresse von i1 in Parameterregister A0
  192. T000038:   MOVEQ.L   #$01,D0        ; Wert 1 in Parameterregister D0
  193. T00003A:   PEA.L     $0018(A7)      ; Adresse von Returnwert auf den Stack
  194. T00003E:   JSR       p1(PC)         ; Aufruf von 'p1'
  195. T000042:   LEA.L     $001C(A7),A7   ; Stackkorrektur und Ergebnis nach d:
  196. T000046:   LEA.L     (A7),A0
  197. T000048:   LEA.L     $0012(A2),A1
  198. T00004C:   MOVE.L    (A0)+,(A1)+
  199. T00004E:   MOVE.L    (A0)+,(A1)+
  200. T000050:   MOVE.W    (A0)+,(A1)+
  201. T000052:   MOVE.W    (A2),-(A7)     ; i1 auf Stack
  202. T000054:   LEA.L     $001C(A2),A0   ; d  auf Stack
  203. T000058:   MOVE.L    -(A0),-(A7)
  204. T00005A:   MOVE.L    -(A0),-(A7)
  205. T00005C:   MOVE.W    -(A0),-(A7)
  206. T00005E:   LEA.L     ,A0            ; Adresse von Formatstring nach A0
  207. T000064:   JSR       printf(PC)     ; Aufruf von 'printf'
  208. T000068:   LEA.L     $000C(A7),A7   ; Stackkorrektur und Prozedurende:
  209. T00006C:   LEA.L     $000A(A7),A7
  210. T000070:   MOVEA.L   (A7)+,A2
  211. T000072:   RTS
  212.  
  213.  
  214.           .DATA
  215.  
  216.           .MODULE LOCAL
  217.  
  218. D000000:   .DC.W   $643A ,$2025 ,$3130 ,$6C66 ,$2020 ,$6931 ,$3A20 ,$2531
  219. D000010:   .DC.W   $3064 ,$0A00 ,$3FFB ,$FCD6 ,$E9B9 ,$CB1A ,$F989
  220.  
  221.  
  222.           .BSS
  223.  
  224.           .MODULE LOCAL
  225.  
  226. i1::
  227. B000000:   .DS.B   2
  228. i2::
  229. B000002:   .DS.B   2
  230. i3::
  231. B000004:   .DS.B   2
  232. i4::
  233. B000006:   .DS.B   2
  234. d1::
  235. B000008:   .DS.B   10
  236. d::
  237. B000012:   .DS.B   10
  238.  
  239.  
  240.           .END
  241.  
  242. Stackframe beim Call von p1:
  243.  
  244.  Datenregister | Stack        | Adreßregister
  245. ---------------|--------------|----------------
  246. D0:  1         | ADR( i4)     |  A0:  ADR( i1)
  247. D1:  2         | 4            |  A1:  ADR( i2)
  248. D2:  3         | ADR( i3)     |
  249.                | ADR( d1)     |
  250.                | 0.123456789  |
  251.                | ADR( return) |
  252.  
  253. Dabei ist ADR( return) die lokale Adresse, an der der Returnwert gespeicht
  254. wird. Dieser ist ja vom Typ 'double' und wird daher nicht in D0/A0 übergeben.
  255.  
  256. Stackframe beim Call von 'printf'
  257.  
  258.  Datenregister | Stack        | Adreßregister
  259. ---------------------------------------------------------
  260. D0:  -         | i1           |  A0:  ADR( Formatstring)
  261. D1:  -         | d            |  A1:  -
  262. D2:  -         |              |
  263.  
  264. Der Formatstring ist ein fester Parameter und wird deshalb nach Standard-
  265. konvention (hier: Register A0 für ersten Adreßparameter) übergeben.
  266.  
  267. Das ganze ist wohl nicht ganz einfach zu implementieren. Ich glaube aber,
  268. daß sich der Aufwand lohnt. Man hätte dann echtes Multilanguage Programming
  269. auf dem ST/TT.
  270.  
  271. END
  272.  
  273.